package cn.jimmie.learn.sdk.util;

import android.app.Activity;
import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Resources;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import cn.jimmie.learn.pbc.resource.ISdk;
import cn.jimmie.learn.pbc.resource.Plugin;
import cn.jimmie.learn.pbc.resource.PluginConst;
import cn.jimmie.learn.pbc.util.Utils;
import dalvik.system.DexClassLoader;

/**
 * function :
 *
 * <p> Create Time:  2019年02月16日 15:35 </p>
 * <p> @author Jimmie.Qian  </p>
 */
public class PluginUtils {
    public static Plugin useDefaultPlugin(Activity ctx) {
        // 1. 查看 /data/data/files , 有则使用
        File dataPlugin = ctx.getFileStreamPath(PluginConst.PLUGIN_NAME);

        // 2. /data/data/files 没有则, 使用 assert中的插件
        if (!dataPlugin.exists()) {
            Utils.extractAssets(ctx, PluginConst.PLUGIN_NAME);
        }

        // 3. 获取插件
        return loadPluginManager(ctx, PluginConst.PLUGIN_NAME);
    }


    public static Plugin loadPluginManager(Context ctx, String pluginName) {
        try {
            //noinspection ConstantConditions
            String mDexPath = ctx.getFileStreamPath(pluginName).getAbsolutePath();
            final String dexOutputPath = ctx.getCacheDir().getAbsolutePath();

            AssetManager assetManager = AssetManager.class.newInstance();
            //noinspection JavaReflectionMemberAccess
            Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);
            addAssetPath.invoke(assetManager, mDexPath);

            Resources superRes = ctx.getResources();
            Resources resources = new Resources(assetManager, superRes.getDisplayMetrics(),
                    superRes.getConfiguration());

            // soLibs
            String soLibsPath = SoUtils.extractSoLibs(ctx, assetManager);

            // ClassLoader
            ClassLoader classLoader = new DexClassLoader(mDexPath,
                    dexOutputPath, soLibsPath, ctx.getClassLoader());

            return new Plugin(classLoader, assetManager, resources);
        } catch (Throwable e) {
            throw new RuntimeException("load plugin resources failure!", e);
        }
    }

    public static ISdk hookPluginInstance(ClassLoader loader) {
        // hook 插件中的单例
        try {
            // 创建单例
            Class<?> klass = loader.loadClass(PluginConst.INSTANCE_NAME);
            Field field = klass.getDeclaredField("sInstance");
            field.setAccessible(true);
            Object instance = field.get(null);
            return (ISdk) instance;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
